home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-04-21 | 6.4 KB | 246 lines | [TEXT/MPS ] |
- // The C++ Booch Components (Version 2.1)
- // (C) Copyright 1990-1993 Grady Booch. All Rights Reserved.
- //
- // Restricted Rights Legend
- // Use, duplication, or disclosure is subject to restrictions as set forth
- // in subdivision (c)(1)(ii) of the Rights in Technical Data and Computer
- // Software clause at DFARS 252.227-7013.
- //
- // BCPool.cpp
- //
- // This file contains the definitions for the heap storage management class.
-
- #include "BCExcept.h"
- #include "BCPool.h"
-
- union BC_UWord {
- void* p;
- long double d;
- long l;
- };
-
- BC_CPool::BC_CPool(size_t chunkSize)
- : fHead(0),
- fUnusedChunks(0),
- fChunkSize(BC_CPool::Align(chunkSize)),
- fUsableChunkSize(BC_CPool::Align(chunkSize) - BC_CPool::Align(sizeof(BC_SChunk)))
- {
- BC_Assert(fUsableChunkSize, BC_XStorageError("BC_CPool::BC_CPool", BC_kTooSmall));
- }
-
- BC_CPool::~BC_CPool()
- {
- PurgeUnusedChunks();
- BC_SChunk* ptr = fHead;
- while (ptr) {
- BC_SChunk* chunk = ptr;
- ptr = ptr->fNextSizedChunk;
- while (chunk) {
- BC_SChunk* temp = chunk;
- chunk = chunk->fNextChunk;
- delete temp;
- }
- }
- }
-
- void* BC_CPool::Allocate(size_t s)
- {
- size_t alignedSize = BC_CPool::Align(s);
- if (!alignedSize)
- return 0;
- BC_Assert((alignedSize <= fUsableChunkSize),
- BC_XStorageError("BC_CPool::Allocate", BC_kTooLarge));
- BC_SChunk* temp;
- BC_SChunk* previous = 0;
- BC_SChunk* ptr = fHead;
- while (ptr && (alignedSize > ptr->fElementSize)) {
- previous = ptr;
- ptr = ptr->fNextSizedChunk;
- }
- if (!ptr) {
- ptr = GetChunk(alignedSize);
- if (previous)
- previous->fNextSizedChunk = ptr;
- else
- fHead = ptr;
- ptr->fPreviousSizedChunk = previous;
- ptr->fNextSizedChunk = 0;
- ptr->fNextChunk = 0;
- } else if ((alignedSize != ptr->fElementSize) || !ptr->fNextElement) {
- temp = GetChunk(alignedSize);
- if (previous)
- previous->fNextSizedChunk = temp;
- else
- fHead = temp;
- temp->fPreviousSizedChunk = previous;
- if (alignedSize != ptr->fElementSize) {
- ptr->fPreviousSizedChunk = temp;
- temp->fNextSizedChunk = ptr;
- temp->fNextChunk = 0;
- } else if (!ptr->fNextElement) {
- temp->fNextSizedChunk = ptr->fNextSizedChunk;
- temp->fNextChunk = ptr;
- }
- ptr = temp;
- }
- BC_SElement* element = ptr->fNextElement;
- ptr->fNextElement = element->fNextElement;
- return (void*)element;
- }
-
- void BC_CPool::Deallocate(void* p, size_t s)
- {
- size_t alignedSize = BC_CPool::Align(s);
- if (!alignedSize)
- return;
- BC_SChunk* ptr = fHead;
- while (ptr && (alignedSize != ptr->fElementSize))
- ptr = ptr->fNextSizedChunk;
- BC_Assert((ptr != 0), BC_XStorageError("BC_CPool::Deallocate", BC_kMissing));
- BC_SElement* element = (BC_SElement*)p;
- element->fNextElement = ptr->fNextElement;
- ptr->fNextElement = element;
- }
-
- void BC_CPool::Preallocate(BC_Index numberOfChunks)
- {
- for (BC_Index index = 0; (index < numberOfChunks); index++) {
- BC_SChunk* chunk = (BC_SChunk*)(new char[fChunkSize]);
- chunk->fNextChunk = fUnusedChunks;
- fUnusedChunks = chunk;
- }
- }
-
- void BC_CPool::ReclaimUnusedChunks()
- {
- BC_SChunk* chunk;
- BC_SChunk* previous = 0;
- BC_SChunk* ptr = fHead;
- while (ptr) {
- chunk = ptr;
- while (chunk) {
- chunk->fNumberOfElements = fUsableChunkSize / chunk->fElementSize;
- chunk = chunk->fNextChunk;
- }
- BC_SElement* element = ptr->fNextElement;
- while (element) {
- chunk = ptr;
- while (chunk) {
- if (((void*)chunk <= (void*)element) &&
- ((void*)element < (void*)((char*)chunk + fChunkSize))) {
- chunk->fNumberOfElements--;
- break;
- }
- chunk = chunk->fNextChunk;
- }
- element = element->fNextElement;
- }
- BC_SChunk* previousChunk = 0;
- chunk = ptr;
- while (chunk) {
- if (!chunk->fNumberOfElements) {
- if (previousChunk) {
- previousChunk->fNextChunk = chunk->fNextChunk;
- chunk->fNextChunk = fUnusedChunks;
- fUnusedChunks = chunk;
- chunk = previousChunk->fNextChunk;
- } else {
- BC_SChunk* temp = chunk->fNextChunk;
- BC_SChunk* next = chunk->fNextSizedChunk;
- if (temp) {
- if (previous)
- previous->fNextSizedChunk = temp;
- else
- fHead = temp;
- temp->fPreviousSizedChunk = previous;
- temp->fNextSizedChunk = next;
- temp->fNextElement = chunk->fNextElement;
- } else {
- if (previous)
- previous->fNextSizedChunk = next;
- else
- fHead = next;
- }
- if (next) {
- if (temp)
- next->fPreviousSizedChunk = temp;
- else
- next->fPreviousSizedChunk = previous;
- }
- chunk->fNextChunk = fUnusedChunks;
- fUnusedChunks = chunk;
- chunk = temp;
- }
- } else {
- previousChunk = chunk;
- chunk = chunk->fNextChunk;
- }
- }
- previous = ptr;
- ptr = ptr->fNextSizedChunk;
- }
- }
-
- void BC_CPool::PurgeUnusedChunks()
- {
- while (fUnusedChunks) {
- BC_SChunk* chunk = fUnusedChunks;
- fUnusedChunks = chunk->fNextChunk;
- delete chunk;
- }
- }
-
- BC_Index BC_CPool::NumberOfDirtyChunks() const
- {
- BC_Index count = 0;
- BC_SChunk* ptr = fHead;
- while (ptr) {
- BC_SChunk* chunk = ptr;
- ptr = ptr->fNextSizedChunk;
- while (chunk) {
- count++;
- chunk = chunk->fNextChunk;
- }
- }
- return count;
- }
-
- BC_Index BC_CPool::NumberOfUnusedChunks() const
- {
- BC_Index count = 0;
- BC_SChunk* chunk = fUnusedChunks;
- while (chunk) {
- count++;
- chunk = chunk->fNextChunk;
- }
- return count;
- }
-
- BC_CPool::BC_SChunk* BC_CPool::GetChunk(size_t s)
- {
- BC_SChunk* chunk;
- if (fUnusedChunks) {
- chunk = fUnusedChunks;
- fUnusedChunks = chunk->fNextChunk;
- } else {
- chunk = (BC_SChunk*)(new char[fChunkSize]);
- BC_Assert((chunk != 0), BC_XStorageError("BC_CPool::GetChunk", BC_kOutOfMemory));
- }
- chunk->fElementSize = s;
- chunk->fNumberOfElements = fUsableChunkSize / s;
- char* start = (char*)chunk + Align(sizeof(BC_SChunk));
- char* stop = &start[(chunk->fNumberOfElements - 1) * chunk->fElementSize];
- for (char* element = start; (element < stop); element += s)
- ((BC_SElement*)element)->fNextElement = (BC_SElement*)(element + s);
- ((BC_SElement*)stop)->fNextElement = 0;
- chunk->fNextElement = (BC_SElement*)start;
- return chunk;
- }
-
- size_t BC_CPool::Align(size_t s)
- {
- size_t alignedSize = s + sizeof(BC_UWord) - 1;
- alignedSize -= alignedSize % sizeof(BC_UWord);
- return alignedSize;
- }
-